 (function(root) {
     var cloud = function(data) {
         // 判断this是不是cloud实例
         if (!(this instanceof cloud)) {
             // 变为实例
             // eslint-disable-next-line new-cap
             return new cloud(data)
         }
         // 拿到直接写在cloud里的参数
         this.wraper = data
     }

     // 测试
     // 上一道工序的数据
     // 有返回值
     // 一般第一个参数是上一个数据的返回source，后面写的都是参数
     // 由于实力有限，流少部分函数做效果
     cloud.filters = function(source) {

     }

     // 工具主体
     // cloud.each = cloud.forEach = function(obj, callback) {
     //     if (typeof callback != 'function') {
     //         throw new Error("muse be a function")
     //     }
     //     if (Array.isArray(obj)) {
     //         var a = []
     //         for (let i = 0; i < obj.length; i++) {
     //             a = callback.call(null, obj[i])
     //         }
     //     } else {

     //         var _keys = obj.keys
     //             // console.log(_obj);
     //         for (let i = 0; i < _keys.length; i++) {
     //             return callback.call(callback, key[i], obj[key[i]])
     //         }
     //     }
     //     throw new Error('This is not an object or an array')
     // }
     // cloud.isObject = function(obj) {
     //     if (typeof obj === 'object') {
     //         return true
     //     }
     //     return false
     // }

     // 防抖
     cloud.debounce = function(fn, delay) {
             let timer = null
             clearTimeout(timer)
             return function() {
                 timer = setTimeout(() => {
                     fn.apply(this, arguments)
                 }, delay)
             }
         }
         // 节流
     cloud.throttle = function(fn, delay) {
             let valid = true
             return function() {
                 if (valid) {
                     setTimeout(() => {
                         fn.apply(this, arguments)
                         valid = true
                     }, delay)
                     valid = false
                 } else {
                     return false
                 }
             }
         }
         // compose函数
     cloud.compose = function() {
             const args = [].slice.apply(arguments)
             console.log(arguments)
             console.log(args)
             return function(num) {
                 var _result = num
                 for (var i = args.length - 1; i >= 0; i--) {
                     _result = args[i](_result)
                 }
                 return _result
             }
         }
         // array
         // 去除第一个
     cloud.first = cloud.head = cloud.take = function(array, n = 1) {
             const arr = []
             for (let i = 0; i < array.length; i++) {
                 if (i > n - 1) {
                     arr.push(array[i])
                 }
             }
             return arr
         }
         // 多层数组解套
     var flatten = function(input, shallow, strict, output) {
         output = output || []
         var idx = output.length
         for (var i = 0, length = input.length; i < length; i++) {
             var value = input[i]
             if ((Array.isArray(value))) {
                 if (shallow) {
                     var j = 0
                     var len = value.length
                     while (j < len) output[idx++] = value[j++]
                 } else {
                     flatten(value, shallow, strict, output)
                     idx = output.length
                 }
             } else if (!strict) {
                 output[idx++] = value
             }
         }
         return output
     }

     cloud.flatten = function(array, shallow) {
         return flatten(array, shallow, false)
     }

     // 数组去重
     cloud.union = function(fn) {
         const arg = arguments
         const arr = []
         for (const item in arg) {
             const a = arg[item]
             if (Array.isArray(a)) {
                 for (let i = 0; i < a.length; i++) {
                     console.log(a[i])
                     const target = fn ? fn(a[i]) : a[i]
                     if (arr.indexOf(target) === -1) { arr.push(target) }
                 }
             }
         }
         return arr
     }

     // 取交集
     cloud.intersection = function() {
             const arg = arguments
             const arr = arg[0]
             for (let i = 1; i < arg.length; i++) {
                 const a = arg[i]
                 let len = arr.length
                 for (let j = 0; j < len; j++) {
                     const target = arr[j]
                     if (a.indexOf(target) === -1) {
                         arr.splice(i + 1, 1)
                         len -= 1
                     }
                 }

             }
             return arr
         }
         // 数组转换矩阵
     cloud.unzip = function(array) {
         const len = array.reduce((prev, cur) => {
             if (prev.length < cur.length) prev = cur
             return prev
         }, array[0]).length
         const arr = new Array(len).fill(1).map(() => {
             // eslint-disable-next-line no-array-constructor
             return new Array()
         })
         for (let i = 0; i < array.length; i++) {
             const a = array[i]
             for (let j = 0; j < a.length; j++) {
                 arr[j][i] = a[j]
             }
         }
         return arr
     }
     cloud.zip = function() {
             const arg = arguments
             const arr = []
             for (const i in arg) {
                 if (Array.isArray(arg[i])) { arr.push(arg[i]) }
             }
             return cloud.unzip(arr)
         }
         // 数组转对象
     cloud.object = function(list, values) {
         var result = {}
         for (var i = 0, length = list.length; i < length; i++) {
             if (values) {
                 result[list[i]] = values[i]
             } else {
                 result[list[i][0]] = list[i][1]
             }
         }
         return result
     }

     // 底层架构，不要动、

     // 解析出实例里方法
     var beforHook = function(arr, callback) {
             for (var i of arr) {
                 callback(i)
             }
         }
         // 解析出函数名
         // target 实例
     cloud.prossess = function(target) {
             var res = []
             for (var key in target) {
                 res.push(key)
             }
             return res
         }
         // 打开流式编程
     cloud.chain = function(source) {
             // 创建一个特殊实例
             var instance = cloud(source)
             instance._chain = true
             return instance
         }
         // 结束流
         // 接收上一轮返回的值
     cloud.prototype.ending = function() {
             return this.wraper
         }
         // instance 是否为特殊实例， outcome 返回的结果
     var model = function(instance, outcome) {
             if (instance._chain) {
                 // 扩展wrapper属性，存上一层结果。
                 instance.wraper = outcome
                 return instance

             }
         }
         // target 传入cloud实例
     cloud.mixin = function(target) {
         beforHook(cloud.prossess(target), function(key) {
             // 赋值func 为该函数。
             var func = target[key]
                 // 在原型上扩展方法
             cloud.prototype[key] = function() {
                 // 参数写入方法
                 // return func(this.wraper)
                 // 写数组，第一个变量为传递的参数。
                 var decom = [this.wraper]
                     // 合并数组，把argments拆进来。
                 Array.prototype.push.apply(decom, arguments)
                 return model(this, func.apply(this, decom))

             }
         })
     }
     cloud.mixin(cloud)
     root.cloud = cloud

 })(this)